﻿using System;
using System.IO;
using System.Configuration;
using System.Text;
using System.Data;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace T.FAS.Runtime.StateMachine.Engine
{
    /// <summary>
    /// 本地日志服务
    /// </summary>
    public static class LocalLogService
    {
        private static object syncObj = new object();
        private static object syncObj_err = new object();
        private static string isLogNormal = ConfigurationManager.AppSettings["isLogNormal"];
        private static string isLogError = ConfigurationManager.AppSettings["isLogError"];
        private static string logPath = ConfigurationManager.AppSettings["DataAccessLogPath"];

        /// <summary>
        /// 记录异常信息
        /// </summary>
        /// <param name="er">异常信息</param>
        public static void WriteError(Exception er, string Msg = null)
        {
            if (string.IsNullOrEmpty(isLogError) || isLogError.ToLower() != "true")
                return;
            lock (syncObj_err)
            {
                if (er == null)
                    return;
                string errPath = string.Empty;
                try
                {
                    string path = ErrorLogPath;
                    if (Directory.Exists(path) == false)
                        Directory.CreateDirectory(path);
                    path = Path.Combine(path, string.Format("Error-{0}.txt", DateTime.Now.ToString("yyyyMMddHH")));
                    errPath = path;
                    StringBuilder sb = new StringBuilder(100);
                    sb.AppendLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "=========================================================");
                    if (!string.IsNullOrEmpty(Msg))
                        sb.AppendLine("UserMsg:" + Msg);
                    sb.AppendLine("Message:" + er.Message);
                    sb.AppendLine("Stack:" + er.StackTrace);
                    if (er.Data != null)
                    {
                        sb.AppendLine("Data:");
                        foreach (var item in er.Data.Keys)
                        {
                            sb.AppendLine("  " + item + " = " + Convert.ToString(er.Data[item]));
                        }
                    }
                    sb.AppendLine("Full Stack:" + er.ToString());
                    if (er.InnerException != null)
                    {
                        sb.AppendLine("InnerException Message:" + er.InnerException.Message);
                        sb.AppendLine("InnerException Stack:" + er.InnerException.StackTrace);

                        if (er.InnerException.Data != null)
                        {
                            sb.AppendLine("InnerException Data:");
                            foreach (var item in er.InnerException.Data.Keys)
                            {
                                sb.AppendLine("  " + item + " = " + Convert.ToString(er.InnerException.Data[item]));
                            }
                        }
                    }

                    File.AppendAllText(path, sb.ToString());
                }
                catch (System.Exception err)
                {
                    if (string.IsNullOrEmpty(errPath) == false)
                    {
                        try
                        {
                            StringBuilder sb = new StringBuilder(100);
                            sb.AppendLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "=========================================================");
                            sb.AppendLine("Message:" + err.Message);
                            sb.AppendLine("Stack:" + err.StackTrace);
                            File.AppendAllText(errPath, sb.ToString());
                        }
                        catch
                        { }
                    }
                }
            }
        }


        /// <summary>
        /// 记录普通信息
        /// </summary>
        /// <param name="obj">异常信息</param>
        public static void WriteError(object obj)
        {
            if (string.IsNullOrEmpty(isLogNormal) || isLogNormal.ToLower() != "true")
                return;
            lock (syncObj)
            {
                string info = string.Empty;
                if (obj is string)
                    info = obj.ToString();
                else if (obj is DataRow row)
                {
                    StringBuilder sb = new StringBuilder();
                    if (!string.IsNullOrEmpty(row.Table?.TableName))
                        sb.Append($"DataRow所属表：{row.Table.TableName}");
                    sb.Append($"DataRow值:");
                    foreach (var col in row.ItemArray)
                    {
                        sb.Append($"{col},");
                    }
                    info = sb.ToString();
                }
                else
                    info = JsonConvert.SerializeObject(obj, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
                if (string.IsNullOrEmpty(info))
                    return;
                string errPath = string.Empty;
                try
                {
                    string path = NormalLogPath;
                    if (Directory.Exists(path) == false)
                        Directory.CreateDirectory(path);
                    path = Path.Combine(path, string.Format("Error-{0}.txt", DateTime.Now.ToString("yyyyMMddHH")));
                    errPath = path;
                    StringBuilder sb = new StringBuilder(100);
                    sb.AppendLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "=========================================================");
                    sb.AppendLine(info);

                    File.AppendAllText(path, sb.ToString());
                }
                catch (System.Exception err)
                {
                    if (!string.IsNullOrEmpty(errPath))
                    {
                        try
                        {
                            StringBuilder sb = new StringBuilder(100);
                            sb.AppendLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "=========================================================");
                            sb.AppendLine("Message:" + err.Message);
                            sb.AppendLine("Stack:" + err.StackTrace);
                            File.AppendAllText(errPath, sb.ToString());
                        }
                        catch
                        { }
                    }
                }
            }
        }

        /// <summary>
        /// 记录普通信息
        /// </summary>
        /// <param name="er">异常信息</param>
        public static void Write(object obj)
        {
            if (string.IsNullOrEmpty(isLogNormal) || isLogNormal.ToLower() != "true")
                return;
            lock (syncObj)
            {
                string info = string.Empty;
                if (obj is string)
                    info = obj.ToString();
                else if (obj is DataRow row)
                {
                    StringBuilder sb = new StringBuilder();
                    if (!string.IsNullOrEmpty(row.Table?.TableName))
                        sb.Append($"DataRow所属表：{row.Table.TableName}");
                    sb.Append($"DataRow值:");
                    foreach (var col in row.ItemArray)
                    {
                        sb.Append($"{col},");
                    }
                    info = sb.ToString();
                }
                else
                    info = JsonConvert.SerializeObject(obj, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
                if (string.IsNullOrEmpty(info))
                    return;
                string errPath = string.Empty;
                try
                {
                    string path = NormalLogPath;
                    if (Directory.Exists(path) == false)
                        Directory.CreateDirectory(path);
                    path = Path.Combine(path, string.Format("Normal-{0}.txt", DateTime.Now.ToString("yyyyMMddHH")));
                    errPath = path;
                    StringBuilder sb = new StringBuilder(100);
                    sb.AppendLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "=========================================================");
                    sb.AppendLine(info);

                    File.AppendAllText(path, sb.ToString());
                }
                catch (System.Exception err)
                {
                    if (!string.IsNullOrEmpty(errPath))
                    {
                        try
                        {
                            StringBuilder sb = new StringBuilder(100);
                            sb.AppendLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") + "=========================================================");
                            sb.AppendLine("Message:" + err.Message);
                            sb.AppendLine("Stack:" + err.StackTrace);
                            File.AppendAllText(errPath, sb.ToString());
                        }
                        catch
                        { }
                    }
                }
            }
        }

        private static string ErrorLogPath
        {
            get
            {
                return Path.Combine(LogPath, "StateMachineErrorLog");
            }
        }

        private static string NormalLogPath
        {
            get
            {
                return Path.Combine(LogPath, "StateMachineNormalLog");
            }
        }

        private static string LogPath
        {
            get
            {
                if (string.IsNullOrEmpty(logPath))
                {
                    return Path.Combine(Environment.CurrentDirectory, "log");
                }
                else
                    return logPath;
            }
        }
    }

    public enum SQLLogType
    {
        DQL = 0,
        DML = 1,
    }
}
